#define ID_YES     1
#define ID_NO      2
#define ID_OK      3
#define ID_CANCEL  4

#define MB_MAX_ON_STACK 10

class msgBox
{
	string Text[50];

public:

	int width, height;
	int x,y;
	PieEnum winType;

	string title;
	int nOfLines;

	Button buOne,buTwo;
	Vector lol,lul;

	int state;
	

	msgBox()
	{
		width = 450;
		height = 250;
		x = WIN_WIDTH/2-width/2;
		y = WIN_HEIGHT/2+height;
		winType = B_YESNO;
		title = "Window title";
		nOfLines = 0;

		state = NULL;

		
		lol.x = 0;
		lol.y = 0;
		lul.x = 0;
		lul.y = 0;

		buOne.Init(lol,lul);
		buOne.SetColor(0,0,1);
		buOne.SetSpecColor(0.1,0.1,0.9);
		buOne.SetActiveColor(0,0,1);
		buOne.SetActiveSpecColor(0.2,0.2,0.8);
		buOne.SetStyle(FLATCOLOR);
		buOne.SetSpecialStyle(SHADED);
		buOne.SetActiveSpecialStyle(SHADED);
		buOne.SetActiveStyle(SHADED);

		buTwo.Init(lol,lul);
		buTwo.SetColor(0,0,1);
		buTwo.SetSpecColor(0.1,0.1,0.9);
		buTwo.SetActiveColor(0,0,1);
		buTwo.SetActiveSpecColor(0.2,0.2,0.8);
		buTwo.SetStyle(FLATCOLOR);
		buTwo.SetSpecialStyle(SHADED);
		buTwo.SetActiveSpecialStyle(SHADED);
		buTwo.SetActiveStyle(SHADED);
	}

	~msgBox()
	{
		//cout << "lol" << endl;
	}

	void setWinType(PieEnum type)
	{
		winType = type;

	}

	

	void setString(int id,string value)
	{
		if(id < 50 && id >= 0)
			Text[id] = value;
		else
			cout << "Could not add string to message box. invalid id." << endl;
	}

	void addString(string str)
	{
		if(nOfLines < 50)
		{
			Text[nOfLines] = str;
			nOfLines++;
		}
		else
			cout << "Text limit reached of message box!" << endl;
	}

	void reset()
	{
		nOfLines = 0;
		state = NULL;
		winType = B_OK;
		width = 450;
		height = 250;
	}

	void center()
	{
		x=WIN_WIDTH/2-width/2;
		y=WIN_HEIGHT/2+height;
	}

	void render()
	{
		drawBase();
		drawText();
		//handleButtons();

		if(winType==B_OKCANCEL || winType == B_YESNO)
		{
			buOne.Render();
			buTwo.Render();

			if(winType==B_OKCANCEL)
			{
				if(buOne.MouseOver())
					defaultFont.setColor(1,1,1,1);
				else
					defaultFont.setColor(0.5,0.7,1,1);

				defaultFont.setScale(1.3);
				defaultFont.print((x+width/2)-145,y-height+15,"OK");

				if(buTwo.MouseOver())
					defaultFont.setColor(1,1,1,1);
				else
					defaultFont.setColor(0.5,0.7,1,1);

				defaultFont.print((x+width/2)+80,y-height+15,"CANCEL");
			}
			if(winType==B_YESNO)
			{
				if(buOne.MouseOver())
					defaultFont.setColor(1,1,1,1);
				else
					defaultFont.setColor(0.5,0.7,1,1);

				defaultFont.setScale(1.3);
				defaultFont.print((x+width/2)-155,y-height+15,"YES");

				if(buTwo.MouseOver())
					defaultFont.setColor(1,1,1,1);
				else
					defaultFont.setColor(0.5,0.7,1,1);

				defaultFont.print((x+width/2)+115,y-height+15,"NO");
			}
		}
		if(winType == B_OK)
		{
			buOne.Render();


			if(buOne.MouseOver())
				defaultFont.setColor(1,1,1,1);
			else
				defaultFont.setColor(0.5,0.7,1,1);

			defaultFont.setScale(1.3);
			defaultFont.print((x+width/2)-15,y-height+15,"OK");
		}
	}

	void handleButtons()
	{
		if(winType==B_OKCANCEL || winType == B_YESNO)
		{
			lol.x = (x+width/2)-200;
			lol.y = -WIN_HEIGHT+y-height-50;
			lul.x = (x+width/2)-60;
			lul.y = -WIN_HEIGHT+y-height-10;	

			buOne.SetPosition(lol,lul);
			buOne.CheckState(mouseX,mouseY,WIN_HEIGHT,s_leftbutton);
			//buOne.Render();

			lol.x = (x+width/2)+200;
			lol.y = -WIN_HEIGHT+y-height-50;
			lul.x = (x+width/2)+60;
			lul.y = -WIN_HEIGHT+y-height-10;

			buTwo.SetPosition(lol,lul);
			buTwo.CheckState(mouseX,mouseY,WIN_HEIGHT,s_leftbutton);
			//buTwo.Render();

			if(winType==B_OKCANCEL)
			{
				if(buOne.GetState())
				{
					state = ID_OK;
					s_leftbutton = false;
				}
				if(buTwo.GetState())
				{
					state = ID_CANCEL;
					s_leftbutton = false;
				}
			}
			if(winType==B_YESNO)
			{
				if(buOne.GetState())
				{
					state = ID_YES;
					s_leftbutton = false;
				}
				if(buTwo.GetState())
				{
					state = ID_NO;
					s_leftbutton = false;
				}
			}

		}
		if(winType == B_OK)
		{
			lol.x = (x+width/2)-70;
			lol.y = -WIN_HEIGHT+y-height-50;
			lul.x = (x+width/2)+70;
			lul.y = -WIN_HEIGHT+y-height-10;	

			buOne.SetPosition(lol,lul);
			buOne.CheckState(mouseX,mouseY,WIN_HEIGHT,s_leftbutton);

			if(buOne.GetState())
			{
				state = ID_OK;
				s_leftbutton = false;
			}
		}
	}

	void drawText()
	{
		for(int counter =0;counter < nOfLines;counter++)
		{
			defaultFont.setColor(0.5,0.7,1,1);
			defaultFont.setShadow(0,0,0.3,1);
			defaultFont.setShadowOffset(2);
			
			defaultFont.setScale(0.85);
			defaultFont.print(x+20,y-70-(counter*20),Text[counter]);
		}
	}

	void drawBase()
	{
		glColor4f(0.0f,0.0f,0.80f,0.95f);
		glBegin(GL_QUADS);
		glVertex2i(x,y);
		glVertex2i(x+width,y);	
		glColor4f(0.0f,0.0f,0.8f,0.95f);
		glVertex2i(x+width,y-height);
		glVertex2i(x,y-height);
		glEnd();

		glLineWidth(2.0f);
		glColor3f(0.0f,0.0f,1.0f);
		glBegin(GL_LINE_LOOP);
		glVertex2i(x+1,y-21);
		glVertex2i(x+width-1,y-21);	
		glVertex2i(x+width-1,y-height+50);
		glVertex2i(x+1,y-height+50);
		glEnd();

		glColor3f(0.0f,0.5f,0.95f);
		glBegin(GL_QUADS);
		glVertex2i(x,y);
		glVertex2i(x+width,y);	
		glColor3f(0.0f,0.2f,0.9f);
		glVertex2i(x+width,y-30);
		glVertex2i(x,y-30);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.4f);
		glBegin(GL_QUADS);
		glVertex2i(x,y-height+60);
		glVertex2i(x+width,y-height+60);	
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width,y-height+100);
		glVertex2i(x,y-height+100);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.4f);
		glBegin(GL_QUADS);
		glVertex2i(x,y-30);
		glVertex2i(x+width,y-30);	
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width,y-70);
		glVertex2i(x,y-70);
		glEnd();

		glColor3f(0.0f,0.2f,0.9f);
		glBegin(GL_QUADS);
		glVertex2i(x,y-height+60);
		glVertex2i(x+width,y-height+60);	
		glColor3f(0.0f,0.5f,0.95f);
		glVertex2i(x+width,y-height);
		glVertex2i(x,y-height);
		glEnd();

		defaultFont.setColor(0.5,0.7,1,1);
		defaultFont.setShadow(0,0,0.3,1);
		defaultFont.setShadowOffset(3);
		defaultFont.setScale(1.15);

		defaultFont.print(x+10,y-26,title);

		// draw shadows
		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_QUADS);
		glVertex2i(x,y);
		glVertex2i(x,y-height);	
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x-40,y-height);
		glVertex2i(x-40,y);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_QUADS);
		glVertex2i(x+width,y);
		glVertex2i(x+width,y-height);	
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width+40,y-height);
		glVertex2i(x+width+40,y);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_QUADS);
		glVertex2i(x,y);
		glVertex2i(x+width,y);	
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width,y+30);
		glVertex2i(x,y+30);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_QUADS);
		glVertex2i(x,y-height);
		glVertex2i(x+width,y-height);	
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width,y-height-30);
		glVertex2i(x,y-height-30);
		glEnd();

		// draw corner shadows

		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_TRIANGLES);
		glVertex2i(x,y);
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x,y+30);
		glVertex2i(x-40,y);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_TRIANGLES);
		glVertex2i(x,y-height);
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x,y-height-30);
		glVertex2i(x-40,y-height);
		glEnd();

		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_TRIANGLES);
		glVertex2i(x+width,y);
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width,y+30);
		glVertex2i(x+width+40,y);
		glEnd();
	
		glColor4f(0.0f,0.0f,0.0f,0.5f);
		glBegin(GL_TRIANGLES);
		glVertex2i(x+width,y-height);
		glColor4f(0.0f,0.0f,0.0f,0.0f);
		glVertex2i(x+width,y-height-30);
		glVertex2i(x+width+40,y-height);
		glEnd();

	}
};

class msgHandler
{
public:
	msgBox mb;

	void newMsg(string title,PieEnum type)
	{
		mb.reset();
		mb.setWinType(type);
		mb.title = title;
	}

	void newMsg(string title)
	{
		mb.reset();
		mb.title = title;
	}

	void newMsg(string title,PieEnum type,int width,int height)
	{
		mb.reset();
		mb.setWinType(type);
		mb.title = title;
		mb.width = width;
		mb.height = height;
	}

	void addl(string line)
	{
		mb.addString(line);
	}

	void popMsg(int *pPtr)
	{
		mb.center();
		mb.handleButtons();
		//mb.render();

		*pPtr = mb.state;
	}

	void render()
	{
		mb.render();
	}

};

struct boxPar
{
	string title;
	PieEnum type;
	string text[30];
	int nOfStrings;
	int stringSize; // size of biggest string
	int *pCallb;
};

class MSG_SYS{
public:

	msgHandler bitch;
	bool boxStates[MB_MAX_ON_STACK];
	int callbck;
	boxPar bParams[MB_MAX_ON_STACK];

	MSG_SYS()
	{
		callbck = NULL;
		for(int counter =0;counter < MB_MAX_ON_STACK;counter++)
			boxStates[counter] = false;
	}
	~MSG_SYS()
	{
		// lol..
	}

	void update()
	{
		for(int counter = 0;counter < MB_MAX_ON_STACK;counter++)
		{
			if(boxStates[counter])
			{
				//cout << "lol" << endl;
				int w;
				if(bParams[counter].stringSize+50 > 450)
					w = bParams[counter].stringSize+50;
				else
					w = 450;

				bitch.newMsg(bParams[counter].title,bParams[counter].type,w,130+(20*bParams[counter].nOfStrings));

				for(int sCount =0;sCount < bParams[counter].nOfStrings;sCount++)
					bitch.addl(bParams[counter].text[sCount]);

				bitch.popMsg(&callbck);

				if(callbck != NULL)
				{
					cout << "Message box returns: " << callbck << endl;
					if(bParams[counter].pCallb != NULL)
						*bParams[counter].pCallb = callbck;

					boxStates[counter] = false;
					callbck = NULL;
				}
				return;
			}
		}
	}

	void render()
	{
		for(int counter = 0;counter < MB_MAX_ON_STACK;counter++)
		{
			if(boxStates[counter])
			{
				bitch.render();
				return;
			}
		}
	}
	
	void popMsg(string Text,string bTitle,PieEnum type,int *pCallbackVar)
	{
		for(int counter =0;counter < MB_MAX_ON_STACK;counter++)
		{
			if(boxStates[counter] == false)
			{
				cout << "Pushing msgBox to stack, id: " << counter << endl;
				bParams[counter].title = bTitle;
				bParams[counter].type = type;
				bParams[counter].nOfStrings = 0;

				string temp[30];
				const char* buf=Text.c_str();
				stringstream tstream;

				for(int sCount =0;sCount < Text.size();sCount++)
				{
					if(buf[sCount]!='\n')
					{
						tstream << buf[sCount];
					}
					else
					{
						bParams[counter].text[bParams[counter].nOfStrings] = tstream.str();
						bParams[counter].nOfStrings++;
						tstream.str("");
					}
				}
				bParams[counter].text[bParams[counter].nOfStrings] = tstream.str();
				bParams[counter].nOfStrings++;

				int biggestString = 0;

				for(int sCount = 0;sCount < bParams[counter].nOfStrings;sCount++)
				{
					if(defaultFont.stringLength(bParams[counter].text[sCount],0.85f) > biggestString)
						biggestString = defaultFont.stringLength(bParams[counter].text[sCount],0.85f);
				}

				bParams[counter].stringSize = biggestString;
				bParams[counter].pCallb = pCallbackVar;

				boxStates[counter] = true;
				return;
			}
		}
		cout << "MsgBox handler: max number of msgBoxes on stack!!" << endl;
	}
};